package com.hxrk.cecardvr;

import java.util.ArrayList;

/**
 * reference apache commons <a href="http://commons.apache.org/codec/">http://commons.apache.org/codec/</a>
 *
 * @author Aub
 */
public class Hex {
    /**
     * 用于建立十六进制字符的输出的小写字符数组
     */
    private static final char[] DIGITS_LOWER = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    /**
     * 用于建立十六进制字符的输出的大写字符数组
     */
    private static final char[] DIGITS_UPPER = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    /**
     * 将字节数组转换为十六进制字符数组
     *
     * @param data byte[]
     * @return 十六进制char[]
     */
    public static char[] encodeHex(byte[] data, int length) {
        return encodeHex(data, length, true);
    }

    /**
     * 将字节数组转换为十六进制字符数组
     *
     * @param data        byte[]
     * @param toLowerCase <code>true</code> 传换成小写格式 ， <code>false</code> 传换成大写格式
     * @return 十六进制char[]
     */
    public static char[] encodeHex(byte[] data, int length, boolean toLowerCase) {
        return encodeHex(data, length, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
    }

    /**
     * 将字节数组转换为十六进制字符数组
     *
     * @param data     byte[]
     * @param toDigits 用于控制输出的char[]
     * @return 十六进制char[]
     */
    protected static char[] encodeHex(byte[] data, int length, char[] toDigits) {
        int l = length;
        if (length > data.length)
            l = data.length;
        char[] out = new char[l << 1];
        // two characters form the hex value.
        for (int i = 0, j = 0; i < l; i++) {
            out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
            out[j++] = toDigits[0x0F & data[i]];
        }
        return out;
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param data byte[]
     * @return 十六进制String
     */
    public static String encodeHexStr(byte[] data, int length) {
        return encodeHexStr(data, length, false);
    }

    public static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param data        byte[]
     * @param toLowerCase <code>true</code> 传换成小写格式 ， <code>false</code> 传换成大写格式
     * @return 十六进制String
     */
    public static String encodeHexStr(byte[] data, int length, boolean toLowerCase) {
        return encodeHexStr(data, length, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param data     byte[]
     * @param toDigits 用于控制输出的char[]
     * @return 十六进制String
     */
    protected static String encodeHexStr(byte[] data, int length, char[] toDigits) {
        return new String(encodeHex(data, length, toDigits));
    }

    /**
     * 将十六进制字符数组转换为字节数组
     *
     * @param data 十六进制char[]
     * @return byte[]
     * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度，将抛出运行时异常
     */
    public static byte[] decodeHex(char[] data) {
        int len = data.length;
        if ((len & 0x01) != 0) {
            throw new RuntimeException("Odd number of characters.");
        }
        byte[] out = new byte[len >> 1];
        // two characters form the hex value.
        for (int i = 0, j = 0; j < len; i++) {
            int f = toDigit(data[j], j) << 4;
            j++;
            f = f | toDigit(data[j], j);
            j++;
            out[i] = (byte) (f & 0xFF);
        }
        return out;
    }

    public static byte[] charToByte(char[] data) {
        int len = data.length;
        byte[] out = new byte[len];
        // two characters form the hex value.
        for (int i = 0; i < len; i++) {
            out[i] = (byte) (data[i] & 0xFF);
        }
        return out;
    }

    /**
     * 将十六进制字符转换成一个整数
     *
     * @param ch    十六进制char
     * @param index 十六进制字符在字符数组中的位置
     * @return 一个整数
     * @throws RuntimeException 当ch不是一个合法的十六进制字符时，抛出运行时异常
     */
    protected static int toDigit(char ch, int index) {
        int digit = Character.digit(ch, 16);
        if (digit == -1) {
            throw new RuntimeException("Illegal hexadecimal character " + ch + " at index " + index);
        }
        return digit;
    }

    /**
     * int转byte
     *
     * @param iSource
     * @param iArrayLen
     * @return
     */
    public static byte[] InttoByteArray(int iSource, int iArrayLen) {
        byte[] bLocalArr = new byte[iArrayLen];

        int index = (iArrayLen > 4 ? 4 : iArrayLen);
        for (int i = 0; i < index; i++) {
            bLocalArr[i] = (byte) (iSource >> 8 * (index - 1 - i) & 0xFF);
        }
        return bLocalArr;
    }

    //long类型转成byte数组
    public static byte[] longToByte(long number) {
        long temp = number;
        byte[] b = new byte[8];
        for (int i = 0; i < b.length; i++) {
            b[i] = new Long(temp & 0xff).byteValue();// 将最低位保存在最低位
            temp = temp >> 8; // 向右移8位 
        }
        return b;
    }

    /**
     * byte转int
     *
     * @param bRefArr
     * @return
     */
    public static int ByteArraytoInt(byte[] bRefArr) {
        int iOutcome = 0;
        byte bLoop;

        int index = (bRefArr.length > 4 ? 4 : bRefArr.length);
        for (int i = 0; i < index; i++) {
            bLoop = bRefArr[i];
            iOutcome |= (bLoop & 0xFF) << (8 * (index - 1 - i));
        }
        return iOutcome;
    }

    public static byte[] DecToBcd(String Number, int Len) {
        byte[] ret = new byte[Len];
        int j = Number.length() - 1;
        for (int i = Len - 1; i >= 0 && j > 0; i--) {
            ret[i] = (byte) (((Number.charAt(j - 1) - 0x30) << 4) + ((Number.charAt(j) - 0x30) % 10));
            j -= 2;
        }
        return ret;
    }

    public static String bcd2Str(byte[] bytes) {
        StringBuffer temp = new StringBuffer(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            temp.append((byte) ((bytes[i] & 0xf0) >>> 4));
            temp.append((byte) (bytes[i] & 0x0f));
        }
        // return temp.toString().substring(0, 1).equalsIgnoreCase("0") ? temp
        // .toString().substring(1) : temp.toString();
        return temp.toString();
    }

    // 字节数组转字符串 ，判断\0结尾
    public static String ToString(byte[] data) {
        try {
            ArrayList<Byte> dataList = new ArrayList<Byte>();
            for (int i = 0; i < data.length; i++) {
                if (data[i] == 0x00) {
                    break;
                } else {
                    dataList.add(data[i]);
                }
            }

            byte[] dataTest = new byte[dataList.size()];
            for (int i = 0; i < dataList.size(); i++) {
                dataTest[i] = dataList.get(i);
            }
            String dataS = new String(dataTest, "GBK");
            return dataS;
        } catch (Exception e) {
        }
        return "";
    }

    /**
     * 判断字节数组中是否有0
     *
     * @param data 字节数组
     * @return 终结符0之前的字节数组
     */
    public static byte[] byteSplit(byte[] data) {
        try {
            int i;
            for (i = 0; i < data.length; i++) {
                if (data[i] == 0x00) {
                    break;
                }
            }

            if (i == 0)
                return null;

            byte[] des = new byte[i];
            System.arraycopy(data, 0, des, 0, i);

            return des;

        } catch (Exception e) {
            LogUtils.e(Hex.class.getSimpleName(), e.toString());
        }
        return null;
    }

    public static String ToAscll(String str) {
        byte[] b = str.getBytes();
        int[] in = new int[b.length];
        for (int i = 0; i < in.length; i++) {
            in[i] = b[i] & 0xff;
        }
        String data = "";
        for (int j = 0; j < in.length; j++) {
            data += Integer.toString(in[j], 0x10);
        }
        return data;
    }

    //字符串转换为ascii
    public static String StringToA(String content) {
        String result = "";
        int max = content.length();
        for (int i = 0; i < max; i++) {
            char c = content.charAt(i);
            int b = (int) c;
            result = result + b;
        }
        return result;
    }

    //ascii转换为string
    public static String AToString(int i) {
        return Character.toString((char) i);
    }

    public static String ASCArrayToString(byte[] asc) {

        if (asc == null || asc.length == 0) return null;

        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < asc.length; i++) {
            stringBuffer.append(Character.toString((char) i));
        }

        return stringBuffer.toString();
    }

    /**
     * 字符串转换为ASCII码
     *
     * @param str
     */
    public static byte[] stringToAscArray(String str) {
        if (str == null) return null;

        char[] chars = str.toCharArray(); //把字符串转换为字符数组
        byte[] asc = new byte[chars.length];

        for (int i = 0; i < chars.length; i++) {//输出结果

            asc[i] = (byte) chars[i];


        }
//		LogUtils.e("Hex","stringToAscArray ="+);

        return asc;
    }

    public static String bytetostring(byte[] buff) {
        String strbuf = "";
        try {
            int i = 0;
            for (; i < buff.length; i++) {
                if (buff[i] == 0) {
                    break;
                }
            }

            if (i > 0) {
                byte[] buff2 = new byte[i];
                System.arraycopy(buff, 0, buff2, 0, i);
                strbuf = new String(buff2, "GBK");
            }
        } catch (Exception e) {
            LogUtils.e("Hex", e.toString());
        }
        return strbuf;
    }

    // 从十六进制字符串到字节数组转换
    public static byte[] HexString2Bytes(String hexstr) {
        byte[] b = new byte[hexstr.length() / 2];
        for (int i = 0, j = 0; i < b.length; i++) {
            char c0 = hexstr.charAt(j++);
            char c1 = hexstr.charAt(j++);
            b[i] = (byte) ((parse(c0) << 4) | parse(c1));
        }
        return b;
    }

    private static int parse(char c) {
        if (c >= 'a')
            return (c - 'a' + 10) & 0x0f;
        if (c >= 'A')
            return (c - 'A' + 10) & 0x0f;
        return (c - '0') & 0x0f;
    }

    public static String[] get905String(byte[] srcbyte, int srcpos, int strnum) {
        try {
            int[] dd = new int[strnum];
            dd[0] = srcbyte.length - 1;
            int index = 0;
            for (int i = srcpos; i < srcbyte.length && index < strnum; i++) {
                if (srcbyte[i] == 0) {
                    dd[index++] = i;
                }
            }
            if (index == strnum) {
                String[] str = new String[strnum];
                for (int i = 0; i < strnum; i++) {
                    str[i] = "";
                    byte[] strbytesub = new byte[i == 0 ? (dd[i] - srcpos) : (dd[i] - dd[i - 1] - 1)];
                    System.arraycopy(srcbyte, i == 0 ? srcpos : (dd[i - 1] + 1), strbytesub, 0, strbytesub.length);
                    if (strbytesub.length > 0) {
                        str[i] = new String(strbytesub, "GBK");
                    }
                }
                return str;
            }
        } catch (Exception e) {
            LogUtils.e("Hex", e.toString());
        }
        return null;
    }

    /**
     * 计算CRC16校验
     *
     * @param data   需要计算的数组
     * @param offset 起始位置
     * @param count  长度
     * @return CRC16校验值
     */
    public static int calcCrc16(byte[] data, int offset, int count) {
        int crc = 0;
        char ii;
        while (--count >= 0) {
            int z = data[offset++];
            crc = crc ^ z << 8;
            ii = 8;
            do {
                if ((crc & 0x8000) != 0) {
                    crc = (crc & 0xFFFF) << 1 ^ 0x1021;
                } else {
                    crc = (crc & 0xFFFF) << 1;
                }
            } while ((--ii) != 0);
        }
        return (crc & 0xFFFF);
    }
}